#!/usr/bin/env python
import os
import sys
import glob
import shutil
import commands
import itertools
from utils.util import Util

class DataOper:

    @staticmethod
    def lock_file(file_path):
        f = open(file_path, 'w')

        import fcntl
        fcntl.fcntl(f.fileno(), fcntl.F_SETFD, 1)
        try:
            fcntl.lockf(f.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB, 0, 0, 0)
        except IOError:
            print "Failure: The system has been started."
            sys.exit(1)

        f.write(str(os.getpid()))
        return f

    @staticmethod
    def make_directory(dir_path):
        real_path = os.path.abspath(os.path.expanduser(dir_path))
        if real_path[-1] == os.sep:
            real_path = real_path[:-1]
        if not os.path.exists(real_path):
            os.makedirs(real_path)

        return real_path

    @staticmethod
    def make_tree(branches, trunk):
        '''make a directory tree in root directory.

        branches is a list of directories to be created.
        trunk is the root directory.
        '''
        top = os.path.expandvars(trunk)
        if not os.path.isdir(top):
            os.makedirs(top)
            print "mkdir %s" % top

        for directory in branches:
            dirx = os.path.join(top, directory)
            if not os.path.exists(dirx):
                os.makedirs(dirx)
                print "mkdir %s" % dirx

    @staticmethod
    def copy_tree(src, dst, filters=[]):
        '''copy SRC directory into DST

        filters are like ["*.txt", "*.xml"]
        '''
        dest = os.path.expandvars(dst)
        srcf = os.path.expandvars(src)
        names = os.listdir(srcf)
        for name in names:
            srcname = os.path.join(srcf, name)
            dstname = os.path.join(dest, name)
            if os.path.isdir(srcname):
                DataOper.copy_tree(srcname, dstname, filters)
        files = [glob.glob(os.path.join(srcf, fl)) for fl in filters]
        names = list(itertools.chain(*files))

        if names:
            if not os.path.isdir(dest):
                os.makedirs(dest)
                print "mkdir %s" % dest
            for name in names:
                shutil.copy2(name, dest)
                print "copy %s to %s" % (name, dest)

    @staticmethod
    def copy_tree_ex(src, dst, excludable_dirs = [], filters = ["*"], ignore_hint = False):
        '''copy SRC directory into DST

        filters are like ["*.txt", "*.xml"]
        '''
        dest = os.path.expandvars(dst)
        srcf = os.path.expandvars(src)
        if not os.path.isdir(dest):
            os.makedirs(dest)
            if not ignore_hint:
                print "mkdir %s" % dest

        names = os.listdir(srcf)
        for name in names:
            srcname = os.path.join(srcf, name)
            dstname = os.path.join(dest, name)
            if os.path.isdir(srcname):
                excludable_flag = False
                for excludable_dir in excludable_dirs:
                    if name == excludable_dir:
                        excludable_flag = True
                if not excludable_flag:
                    DataOper.copy_tree_ex(srcname, dstname, excludable_dirs, filters, ignore_hint)
        files = [glob.glob(os.path.join(srcf, fl)) for fl in filters]
        names = list(itertools.chain(*files))

        for name in names:
            if not os.path.isdir(name):
                try:
                    shutil.copy2(name, dest)
                except IOError:
                    Util.execute_and_output('cp -r %s %s' % (name, dest))
                if not ignore_hint:
                    print "copy %s to %s" % (name, dest)
        return

    @staticmethod
    def copy_file(src, dst):
        dest = os.path.expandvars(dst)
        srcf = os.path.expandvars(src)

        names = glob.glob(srcf)

        if not os.path.isdir(dest):
            os.makedirs(dest)
            print "mkdir %s" % dest
        for f in names:
            try:
                shutil.copy2(f, dest)
            except IOError:
                Util.execute_and_output('cp -f %s %s' % (f, dest))
            print "copy %s to %s" % (f, dest)

    @staticmethod
    def rename_file(src, new_filename):
        srcf  = os.path.expandvars(src)
        names = glob.glob(srcf)

        if len(names) > 1:
            print "error: names is more in rename_file()."
        for fname in names:
            file_root = fname[:fname.rfind(os.sep)]
            os.rename(fname, file_root + os.sep + new_filename)

    @staticmethod
    def copy_directory(src, dst, filter_str):

        if os.path.isdir(src):
            filters = filter_str.split('|')
            DataOper.copy_tree(src, dst, filters)
        else:
            DataOper.copy_file(src, dst)

    @staticmethod
    def copy_directorys(filespec):
        for src, dst, filter_str in filespec:
            DataOper.copy_directory(src, dst, filter_str)

    @staticmethod
    def copy_files(filespec):
        '''copy files into specific destination.

        filespec is a list of (src, dst).
        '''
        for src, dst in filespec:
            dest = os.path.expandvars(dst)
            srcf = os.path.expandvars(src)
            if not os.path.isdir(dest):
                os.makedirs(dest)
                print "mkdir %s" % dest
            for fpath in glob.glob(srcf):
                shutil.copy2(fpath, dest)
                print "copy %s to %s" % (fpath, dest)

if __name__ == '__main__':
    pass
